﻿using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Linq.Expressions;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace DbFactory.Base
{
    public class BaseTenantRepository<T> : IBaseTenantRepository<T> where T : BaseModel
    {

        public IDatabaseConnection connection = ConnectionFactory.createConnetction("mysql");
        private readonly IHttpContextAccessor _httpContextAccessor;
        public string conStr;

        public BaseTenantRepository(string tenant)
        {
            if (string.IsNullOrEmpty(tenant))
            {
                throw new Exception("租户不存在");
            }
            //查询租户数据库连接
            connection.connect();
            BaseTenant nowTenant = connection.QueryList<BaseTenant>($" and Code='{tenant}' ").FirstOrDefault();
            if (nowTenant == null || string.IsNullOrEmpty(nowTenant.ConnectionString))
            {
                throw new Exception("租户不存在");
            }
            connection.disconnect();
            conStr = nowTenant.ConnectionString;
        }

        public BaseTenantRepository(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
            //根据不同租户使用不同的数据库连接
            var tenant = _httpContextAccessor.HttpContext.Items["tenant"].ToString();
            if (string.IsNullOrEmpty(tenant))
            {
                throw new Exception("租户不存在");
            }
            //查询租户数据库连接
            
            connection.connect();
            BaseTenant nowTenant = connection.QueryList<BaseTenant>($" and Code='{tenant}' ").FirstOrDefault();
            if (nowTenant == null|| string.IsNullOrEmpty(nowTenant.ConnectionString))
            {
                throw new Exception("租户不存在");
            }
            connection.disconnect();
            conStr = nowTenant.ConnectionString;
        }

        public void add(T m)
        {
            try
            {
                connection.connect(conStr);
                connection.insert<T>(m);
                connection.disconnect();
            }
            catch (Exception)
            {
                if (connection.connectState() != ConnectionState.Closed)
                {
                    connection.disconnect();
                }
                throw;
            }
        }

        public async Task addAsync(T m)
        {
            try
            {
                connection.connect(conStr);
                await connection.insertAsync<T>(m);
                connection.disconnect();
            }
            catch (Exception)
            {
                if (connection.connectState() != ConnectionState.Closed)
                {
                    connection.disconnect();
                }
                throw;
            }
        }


        public void add(T m, DbTransaction transaction)
        {
            try
            {
                connection.connect(conStr);
                connection.insert<T>(m, transaction);
                connection.disconnect();
            }
            catch (Exception)
            {
                if (connection.connectState() != ConnectionState.Closed)
                {
                    connection.disconnect();
                }
                throw;
            }
        }



        public async Task addAsync(T m, DbTransaction transaction)
        {
            try
            {
                connection.connect(conStr);
                await connection.insertAsync<T>(m, transaction);
                connection.disconnect();
            }
            catch (Exception)
            {
                if (connection.connectState() != ConnectionState.Closed)
                {
                    connection.disconnect();
                }
                throw;
            }
        }


        public void update(T m)
        {
            connection.connect(conStr);
            connection.update<T>(m);
            connection.disconnect();
        }

        public void update(T m, DbTransaction transaction)
        {
            connection.connect(conStr);
            connection.update<T>(m, transaction);
            connection.disconnect();
        }


        public void delete(string id)
        {
            connection.connect(conStr);
            connection.delete<T>(id, "id");
            connection.disconnect();
        }


        public T getOne(string id)
        {
            connection.connect(conStr);
            T one = connection.QueryFirst<T>(id);
            connection.disconnect();
            return one;
        }


        public T getOneWhere(string where)
        {
            connection.connect(conStr);
            T one = connection.QueryFirstWhere<T>(where);
            connection.disconnect();
            return one;
        }


        public IEnumerable<T> getList(string where)
        {
            connection.connect(conStr);
            IEnumerable<T> list = connection.QueryList<T>(where);
            connection.disconnect();
            return list;
        }


        public IEnumerable<T> getList(Expression<Func<T, bool>> expression)
        {
            connection.connect(conStr);
            IEnumerable<T> list = connection.QueryList<T>(expression);
            connection.disconnect();
            return list;
        }


        public IEnumerable<T> getList(int page, int pageSize)
        {
            connection.connect(conStr);
            IEnumerable<T> list = connection.QueryList<T>(pageSize, page);
            connection.disconnect();
            return list;
        }
        public IEnumerable<T> getList(int page, int pageSize,string orderby,bool desc)
        {
            connection.connect(conStr);
            IEnumerable<T> list = connection.QueryList<T>(pageSize, page);
            connection.disconnect();
            return list;
        }


        public IEnumerable<T> getList(string where, int page, int pageSize)
        {
            connection.connect(conStr);
            IEnumerable<T> list = connection.QueryList<T>(where, pageSize, page);
            connection.disconnect();
            return list;
        }


        public IEnumerable<T> getList(Expression<Func<T, bool>> expression, int page, int pageSize)
        {
            connection.connect(conStr);
            IEnumerable<T> list = connection.QueryList<T>(expression, pageSize,page);
            connection.disconnect();
            return list;
        }


        public int getCount(string where)
        {
            connection.connect(conStr);
            int count = connection.GetCount<T>(where);
            connection.disconnect();
            return count;
        }



        public void createTable()
        {
            connection.connect(conStr);
            connection.CreateTable<T>();
            connection.disconnect();
        }


        public TableInfo getTableInfo()
        {
            string t= typeof(T).Name.ToLower();
            connection.connect(conStr);
            var rs = connection.GetTableInfo(t);
            connection.disconnect();
            return rs;
        }


        public List<string> getTbNameList()
        {
            connection.connect(conStr);
            var rs = connection.GetTbNameList();
            connection.disconnect();
            return rs;
        }



    }

}
